namespace hms::swe
{

template<typename MeshType>
template<BlockLocation loc>
void SolverThread<MeshType>::computeFluxes_vec(
	const MeshBase<MeshType>& mesh,
	const Block<loc>& block,
	[[maybe_unused]] const Array3XsMap& q,
	[[maybe_unused]] const ArrayXXsMap& qBlock,
		  Array3XsMap& fluxes,
	const Ref<const ArrayXXs>& dBlock,
	const Ref<const ArrayXXs>& zBlock,
	const Ref<const ArrayXXs>& hBlock,
	const Ref<const ArrayXXs>& vBlock
){
	using RT = ReconstructionType;
	using ER = EdgeRange;

	#define HLLC(REC_TYPE, EDGE_RANGE, EDGE_BEG, LR_BEG_BLOCK, ROW) \
	fluxScheme_vec( \
		edgeRow<REC_TYPE, EDGE_RANGE>(block, ROW, EDGE_BEG), LR_BEG_BLOCK, \
		mesh, block, q, qBlock, fluxes, dBlock, zBlock, hBlock, vBlock )

	/* the inner edges loop goes from x0-nx and y0-ny. If the block location is
	 * not "inner", then these must be modified and additional loops run. */
	constexpr Index
		x0 { atRight<loc>() ? 1 : 0 },
		y0 { atTop  <loc>() ? 1 : 0 };
	Index
		ny { block.ny() - ( atBottom<loc>() ? 1 : 0 ) };

	/* horizontal bottom edges for top blocks -> MUSCL */
	if constexpr ( atTop<loc>() ){
		HLLC(
			RT::secondOrder, ER::horizontal,
			block.hBeg(),
			block.template lrBeg_block<ER::horizontal>(),
			0
		);
	}
	/* inner horizontal edges */
	for ( Index y=y0; y<ny+1      ; ++y ){
		HLLC(
			( recType<loc, ER::horizontal>() ), ER::horizontal,
			block.hBeg() + y*block.ih().mesh.nx,
			block.template lrBeg_block<ER::horizontal>() + y*block.nxRead(),
			y
		);
	}
	/* horizontal top edges for bottom blocks -> MUSCL */
	if constexpr ( atBottom<loc>() ){
		Index
			nEdgesToAdd { block.ny() * block.ih().mesh.nx },
			nCellsToAdd { block.ny() * block.nxRead() };

		HLLC(
			RT::secondOrder, ER::horizontal,
			block.hBeg() + nEdgesToAdd,
			block.template lrBeg_block<ER::horizontal>() + nCellsToAdd,
			block.ny()
		);
	}

	for ( Index y=0; y<block.ny(); ++y ){
		/* vertical left edges for right blocks -> MUSCL */
		if constexpr ( atRight<loc>() ){
			HLLC(
				RT::secondOrder, ER::vertical,
				block.vBeg() + y*(block.ih().mesh.nx + 1),
				block.template lrBeg_block<ER::vertical>() + y*block.nxRead(),
				y
			);
		}
		/* inner vertical edges */
		HLLC(
			( recType<loc, ER::vertical>() ), ER::vertical,
			block.vBeg() + x0 + y*(block.ih().mesh.nx + 1),
			block.template lrBeg_block<ER::vertical>() + x0 + y*block.nxRead(),
			y
		);
		/* vertical right edges for left blocks -> MUSCL */
		if constexpr ( atLeft<loc>() ){
			HLLC(
				RT::secondOrder, ER::vertical,
				block.vBeg() + block.nx() + y*(block.ih().mesh.nx + 1),
				block.template lrBeg_block<ER::vertical>() + block.nx() + y*block.nxRead(),
				y
			);
		}
	}

	#undef HLLC
}

} // namespace hms::swe
